/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.bluetooth;

import android.content.Context;

import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.mtksettingslib.bluetooth.BluetoothCallback;
import com.android.mtksettingslib.bluetooth.CachedBluetoothDevice;
import com.android.mtksettingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.mtksettingslib.bluetooth.LocalBluetoothManager;
import com.android.mtksettingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.ActionButtonsPreference;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.util.Log;
import android.bluetooth.BluetoothAdapter;

/**
 * This class adds two buttons: one to connect/disconnect from a device (depending on the current
 * connected state), and one to "forget" (ie unpair) the device.
 */
public class BluetoothDetailsButtonsController extends BluetoothDetailsController
        implements BluetoothCallback {
    private static final String KEY_ACTION_BUTTONS = "action_buttons";
    private boolean mIsConnected;
    private static final String TAG = "BluetoothDetailsButtonsController";

    private boolean mConnectButtonInitialized;
    private ActionButtonsPreference mActionButtons;
    private LocalBluetoothManager mLocalManager;
    private CachedBluetoothDeviceManager mDeviceManager;
    private static BluetoothAdapter mAdapter;

    public BluetoothDetailsButtonsController(Context context, PreferenceFragmentCompat fragment,
            CachedBluetoothDevice device, Lifecycle lifecycle, LocalBluetoothManager bluetoothManager) {
        super(context, fragment, device, lifecycle);
        mIsConnected = isConnected();
        if (bluetoothManager != null) {
            mLocalManager = bluetoothManager;
            mDeviceManager = mLocalManager.getCachedDeviceManager();
        }
        mAdapter = BluetoothAdapter.getDefaultAdapter();
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d(TAG,"onPause");
        if (mLocalManager != null) {
            mLocalManager.getEventManager().unregisterCallback(this);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG,"onResume");
        if (mLocalManager != null) {
            mLocalManager.getEventManager().registerCallback(this);
        }
    }
    @Override
    public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
        Log.d(TAG,"onDeviceBondStateChanged,bondState = " + bondState);
        if (bondState == BluetoothDevice.BOND_BONDING) {
            refresh();
        }
    }

    @Override
    public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state,
                                                int bluetoothProfile) {
        Log.d(TAG, "onProfileConnectionStateChanged() device: " +  BluetoothUtils.getMaskAddress(cachedDevice.getDevice()) +
                ", state: " + state + ", bluetoothProfile: " + bluetoothProfile);
        if (bluetoothProfile == BluetoothProfile.LE_AUDIO) {
            refresh();
        }
    }
    private void onForgetButtonPressed() {
        ForgetDeviceDialogFragment fragment =
                ForgetDeviceDialogFragment.newInstance(mCachedDevice.getAddress());
        fragment.show(mFragment.getFragmentManager(), ForgetDeviceDialogFragment.TAG);
    }

    private void onConnectButtonPressed() {
        if (mCachedDevice.getLeAudioStatus() == BluetoothDevice.LE_ADUIO_STATE_ON) {
            String leStr = mCachedDevice.findLeAddress();
            String le1Str = "";
            String le2Str = "";
            if (leStr != null) {
                String[] deviceInfo = leStr.split(";");
                if (deviceInfo.length > 1) {
                    le1Str = deviceInfo[0];
                    le2Str = deviceInfo[1];
                }
            }
            Log.d(TAG,"onConnectButtonPressed,le1Str = " + le1Str + ",le2Str = " + le2Str);
            if (mAdapter != null && !("".equals(le1Str)) && !("".equals(le2Str))) {
                BluetoothDevice le1Device = mAdapter.getRemoteDevice(le1Str);
                BluetoothDevice le2Device = mAdapter.getRemoteDevice(le2Str);
                if (le1Device != null) {
                    if(le1Device.getBondState() == BluetoothDevice.BOND_BONDED) {
                        Log.d(TAG, "connect to LE1");
                        mAdapter.connectAllEnabledProfiles(le1Device);
                    }
                }
                if (le2Device != null) {
                    if (le2Device.getBondState() == BluetoothDevice.BOND_BONDED) {
                        Log.d(TAG, "Connect to LE2");
                        mAdapter.connectAllEnabledProfiles(le2Device);
                    }
                }
            }
        }else {
            Log.d(TAG,"onConnectButtonPressed");
            mCachedDevice.connect();
        }
    }

    private void onDisconnectButtonPressed() {
        if (mCachedDevice.getLeAudioStatus() == BluetoothDevice.LE_ADUIO_STATE_ON) {
            String leStr = mCachedDevice.findLeAddress();
            String le1Str = "";
            String le2Str = "";
            if (leStr != null) {
                String[] deviceInfo = leStr.split(";");
                if (deviceInfo.length > 1) {
                    le1Str = deviceInfo[0];
                    le2Str = deviceInfo[1];
                }
            }
            Log.d(TAG,"onDisconnectButtonPressed,le1Str = " + le1Str + ",le2Str = " + le2Str);
            if (mAdapter != null && !("".equals(le1Str)) && !("".equals(le2Str))) {
                BluetoothDevice le1Device = mAdapter.getRemoteDevice(le1Str);
                BluetoothDevice le2Device = mAdapter.getRemoteDevice(le2Str);
                if (le1Device != null) {
                    if (le1Device.getBondState() == BluetoothDevice.BOND_BONDED) {
                        Log.d(TAG, "disconnect to LE1");
                        mAdapter.disconnectAllEnabledProfiles(le1Device);
                    }
                }

                if (le2Device != null) {
                    if (le2Device.getBondState() == BluetoothDevice.BOND_BONDED) {
                        Log.d(TAG, "disconnect to LE2");
                        mAdapter.disconnectAllEnabledProfiles(le2Device);
                    }
                }
            }
        }else {
            Log.d(TAG,"onDisconnectButtonPressed");
            mCachedDevice.disconnect();
        }
    }

    private boolean isBusy() {
        if (mCachedDevice.getLeAudioStatus() == BluetoothDevice.LE_ADUIO_STATE_ON) {
            String leStr = mCachedDevice.findLeAddress();
            String le1Str = "";
            String le2Str = "";
            if (leStr != null) {
                String[] deviceInfo = leStr.split(";");
                if (deviceInfo.length > 1) {
                    le1Str = deviceInfo[0];
                    le2Str = deviceInfo[1];
                }
            }
            if (mAdapter != null && mDeviceManager != null && !("".equals(le1Str)) &&
                    !("".equals(le2Str))) {
                boolean isLe1Busy = false;
                boolean isLe2Busy = false;
                BluetoothDevice le1Device = mAdapter.getRemoteDevice(le1Str);
                BluetoothDevice le2Device = mAdapter.getRemoteDevice(le2Str);
                CachedBluetoothDevice cachedLe1Device = mDeviceManager.findDevice(le1Device);
                if (cachedLe1Device != null) {
                    isLe1Busy = cachedLe1Device.isBusy();
                }
                CachedBluetoothDevice cachedLe2Device = mDeviceManager.findDevice(le2Device);
                if (cachedLe2Device != null) {
                    isLe2Busy = cachedLe2Device.isBusy();
                }
                Log.d(TAG,"isBusy,isLe1Busy = " + isLe1Busy + ",isLe2Busy = " + isLe2Busy);
                if (isLe1Busy || isLe2Busy) {
                    return true;
                }
            }
        }else {
            Log.d(TAG,"isBusy");
            return mCachedDevice.isBusy();
        }
        return false;
    }

    private boolean isConnected() {
        if (mCachedDevice.getLeAudioStatus() == BluetoothDevice.LE_ADUIO_STATE_ON) {
            String leStr = mCachedDevice.findLeAddress();
            String le1Str = "";
            String le2Str = "";
            if (leStr != null) {
                String[] deviceInfo = leStr.split(";");
                if (deviceInfo.length > 1) {
                    le1Str = deviceInfo[0];
                    le2Str = deviceInfo[1];
                }
            }
            if (mAdapter != null && mDeviceManager != null && !("".equals(le1Str)) &&
                    !("".equals(le2Str))) {
                boolean isLe1Connected = false;
                boolean isLe2Connected = false;
                BluetoothDevice le1Device = mAdapter.getRemoteDevice(le1Str);
                BluetoothDevice le2Device = mAdapter.getRemoteDevice(le2Str);
                CachedBluetoothDevice cachedLe1Device = mDeviceManager.findDevice(le1Device);
                if (cachedLe1Device != null) {
                    isLe1Connected = cachedLe1Device.isConnected();
                }
                CachedBluetoothDevice cachedLe2Device = mDeviceManager.findDevice(le2Device);
                if (cachedLe2Device != null) {
                    isLe2Connected = cachedLe2Device.isConnected();
                }
                Log.d(TAG,"isConnected ,isLe1Connected = " + isLe1Connected + ",isLe2Connected = " +
                        isLe2Connected);
                if (isLe1Connected || isLe2Connected){
                    return true;
                }
            }
        }else {
            Log.d(TAG,"isConnected");
            return mCachedDevice.isConnected();
        }
        return false;
    }
    @Override
    protected void init(PreferenceScreen screen) {
        mActionButtons = ((ActionButtonsPreference) screen.findPreference(
                getPreferenceKey()))
                .setButton1Text(R.string.forget)
                .setButton1Icon(R.drawable.ic_settings_delete)
                .setButton1OnClickListener((view) -> onForgetButtonPressed())
                .setButton1Enabled(true);
    }

    @Override
    protected void refresh() {
        mActionButtons.setButton2Enabled(!isBusy());

        boolean previouslyConnected = mIsConnected;
        mIsConnected = isConnected();
        if (mIsConnected) {
            if (!mConnectButtonInitialized || !previouslyConnected) {
                mActionButtons
                        .setButton2Text(R.string.bluetooth_device_context_disconnect)
                        .setButton2Icon(R.drawable.ic_settings_close)
                        .setButton2OnClickListener(view -> onDisconnectButtonPressed());
                mConnectButtonInitialized = true;
            }
        } else {
            if (!mConnectButtonInitialized || previouslyConnected) {
                mActionButtons
                        .setButton2Text(R.string.bluetooth_device_context_connect)
                        .setButton2Icon(R.drawable.ic_add_24dp)
                        .setButton2OnClickListener(
                                view -> onConnectButtonPressed());
                mConnectButtonInitialized = true;
            }
        }
    }

    @Override
    public String getPreferenceKey() {
        return KEY_ACTION_BUTTONS;
    }

}